/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package experimental.com.rhythm.commons.validation.bean;

import experimental.com.rhythm.commons.validation.bean.annotation.Constraint;
import com.rhythm.commons.reflections.Reflector;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import static com.rhythm.base.Preconditions.assertNotNull;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Michael J. Lee
 */
public abstract class Bean {

    private final Field[] getConstrainedFields(Object ref) {
        return Reflector.getFieldsWithAnnotationOfType(Constraint.class, ref);
    }

    private ConstraintValidator getValidator(Field field) {
        assertNotNull(field, "Field cannot be null and is.");

        Annotation instance = (Annotation) Reflector.getAnnotationOfType(Constraint.class, field, field);
        assertNotNull(instance, "@Constraint not found on field [" + field.getName() + "]");

        Constraint constraint = instance.annotationType().getAnnotation(Constraint.class);


        try {

            ConstraintValidator validator = (ConstraintValidator) constraint.validatedBy().newInstance();
            validator.initialize(instance);
            return validator;
        } catch (Exception ex) {
            Logger.getLogger(Bean.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    protected final void checkConstraints(Object ref) {
        Field[] fields = getConstrainedFields(ref);
        for (Field aField : fields) {
            try {
                aField.setAccessible(true);
                getValidator(aField).checkConstraint(aField.get(ref));
            } catch (Exception ex) {
                Logger.getLogger(Bean.class.getName()).log(Level.SEVERE, null, ex);
                throw new RuntimeException(ex);//TODO: better exception wrapping
            }
        }
    }

    public abstract void checkConstraints();
}
